﻿#include "pch.h"
#include "Block3.h"
#include "Game.h"

/**
 * 构造方法。
 */
Block3::Block3() {
    mBlocks[1][1].mUsed = mBlocks[2][0].mUsed = mBlocks[2][1].mUsed = mBlocks[2][2].mUsed = TRUE;
}

/**
 * 擦除。
 */
void Block3::Erase() {
    RECT rect = { 0 };

    switch (mShape) {
        case ONE:
            rect.left = Const::GRID_SIZE * (mLine + 1);
            rect.top = Const::GRID_SIZE * (mRow + 1);
            rect.right = rect.left + Const::GRID_SIZE;
            rect.bottom = rect.top + Const::GRID_SIZE;
            Block::EraseRect(&rect);
            rect.left = Const::GRID_SIZE * mLine;
            rect.top = Const::GRID_SIZE * (mRow + 2);
            rect.right = rect.left + Const::GRID_SIZE * 3;
            rect.bottom = rect.top + Const::GRID_SIZE;
            Block::EraseRect(&rect);
            break;
        case TWO:
            rect.left = Const::GRID_SIZE * (mLine + 1);
            rect.top = Const::GRID_SIZE * (mRow + 1);
            rect.right = rect.left + Const::GRID_SIZE;
            rect.bottom = rect.top + Const::GRID_SIZE * 3;
            Block::EraseRect(&rect);
            rect.left = Const::GRID_SIZE * (mLine + 2);
            rect.top = Const::GRID_SIZE * (mRow + 2);
            rect.right = rect.left + Const::GRID_SIZE;
            rect.bottom = rect.top + Const::GRID_SIZE;
            Block::EraseRect(&rect);
            break;
        case THREE:
            rect.left = Const::GRID_SIZE * mLine;
            rect.top = Const::GRID_SIZE * (mRow + 2);
            rect.right = rect.left + Const::GRID_SIZE * 3;
            rect.bottom = rect.top + Const::GRID_SIZE;
            Block::EraseRect(&rect);
            rect.left = Const::GRID_SIZE * (mLine + 1);
            rect.top = Const::GRID_SIZE * (mRow + 3);
            rect.right = rect.left + Const::GRID_SIZE;
            rect.bottom = rect.top + Const::GRID_SIZE;
            Block::EraseRect(&rect);
            break;
        case FOUR:
            rect.left = Const::GRID_SIZE * mLine;
            rect.top = Const::GRID_SIZE * (mRow + 2);
            rect.right = rect.left + Const::GRID_SIZE;
            rect.bottom = rect.top + Const::GRID_SIZE;
            Block::EraseRect(&rect);
            rect.left = Const::GRID_SIZE * (mLine + 1);
            rect.top = Const::GRID_SIZE * (mRow + 1);
            rect.right = rect.left + Const::GRID_SIZE;
            rect.bottom = rect.top + Const::GRID_SIZE * 3;
            Block::EraseRect(&rect);
            break;
    }
}

/**
 * 获取底端所在的行数。底端是指方块最下方的有效格。
 * @return 底端所在的行数
 */
int Block3::GetBottom() {
    if (mShape == ONE) {
        return mRow + 2;
    }
    return mRow + 3;
}

/**
 * 获取顶端所在的行数。顶端是指方块最上方的有效格。
 * @return 顶端所在的行数
 */
int Block3::GetTop() {
    if (mShape == THREE) {
        return mRow + 2;
    }
    return mRow + 1;
}

/**
 * 对不能下落的处理。
 */
void Block3::HandleCannotMoveDown() {
    switch (mShape) {
        case ONE:
            Game::sExistentBlocks[mRow + 1][mLine + 1].mUsed = TRUE;
            Game::sExistentBlocks[mRow + 1][mLine + 1].mColor = mColor;
            for (int j = 0; j <= 2; j++) {
                Game::sExistentBlocks[mRow + 2][mLine + j].mUsed = TRUE;
                Game::sExistentBlocks[mRow + 2][mLine + j].mColor = mColor;
            }
            break;
        case TWO:
            Game::sExistentBlocks[mRow + 2][mLine + 2].mUsed = TRUE;
            Game::sExistentBlocks[mRow + 2][mLine + 2].mColor = mColor;
            for (int i = 1; i <= 3; i++) {
                Game::sExistentBlocks[mRow + i][mLine + 1].mUsed = TRUE;
                Game::sExistentBlocks[mRow + i][mLine + 1].mColor = mColor;
            }
            break;
        case THREE:
            Game::sExistentBlocks[mRow + 3][mLine + 1].mUsed = TRUE;
            Game::sExistentBlocks[mRow + 3][mLine + 1].mColor = mColor;
            for (int j = 0; j <= 2; j++) {
                Game::sExistentBlocks[mRow + 2][mLine + j].mUsed = TRUE;
                Game::sExistentBlocks[mRow + 2][mLine + j].mColor = mColor;
            }
            break;
        case FOUR:
            Game::sExistentBlocks[mRow + 2][mLine].mUsed = TRUE;
            Game::sExistentBlocks[mRow + 2][mLine].mColor = mColor;
            for (int i = 1; i <= 3; i++) {
                Game::sExistentBlocks[mRow + i][mLine + 1].mUsed = TRUE;
                Game::sExistentBlocks[mRow + i][mLine + 1].mColor = mColor;
            }
            break;
    }
}

/**
 * 下落。
 * @return 成功则返回 TRUE，否则返回 FALSE
 */
BOOL Block3::MoveDown() {
    switch (mShape) {
        case ONE:
            if (mRow == 17) {
                this->HandleCannotMoveDown();
                return FALSE;
            }
            if (Game::sExistentBlocks[mRow + 3][mLine].mUsed || 
                Game::sExistentBlocks[mRow + 3][mLine + 1].mUsed || 
                Game::sExistentBlocks[mRow + 3][mLine + 2].mUsed) {
                this->HandleCannotMoveDown();
                return FALSE;
            }
            break;
        case TWO:
            if (mRow == 16) {
                this->HandleCannotMoveDown();
                return FALSE;
            }
            if (Game::sExistentBlocks[mRow + 4][mLine + 1].mUsed || 
                Game::sExistentBlocks[mRow + 3][mLine + 2].mUsed) {
                this->HandleCannotMoveDown();
                return FALSE;
            }
            break;
        case THREE:
            if (mRow == 16) {
                this->HandleCannotMoveDown();
                return FALSE;
            }
            if (Game::sExistentBlocks[mRow + 3][mLine].mUsed || 
                Game::sExistentBlocks[mRow + 4][mLine + 1].mUsed || 
                Game::sExistentBlocks[mRow + 3][mLine + 2].mUsed) {
                this->HandleCannotMoveDown();
                return FALSE;
            }
            break;
        case FOUR:
            if (mRow == 16) {
                this->HandleCannotMoveDown();
                return FALSE;
            }
            if (Game::sExistentBlocks[mRow + 3][mLine].mUsed || 
                Game::sExistentBlocks[mRow + 4][mLine + 1].mUsed) {
                this->HandleCannotMoveDown();
                return FALSE;
            }
            break;
    }

    return Block::MoveDown();
}

/**
 * 左移。
 */
void Block3::MoveLeft() {
    switch (mShape) {
        case ONE:
            if (mLine == 0) {
                return;
            }
            if (Game::sExistentBlocks[mRow + 1][mLine].mUsed || 
                Game::sExistentBlocks[mRow + 2][mLine - 1].mUsed) {
                return;
            }
            break;
        case TWO:
            if (mLine == -1) {
                return;
            }
            if (Game::sExistentBlocks[mRow + 1][mLine].mUsed || 
                Game::sExistentBlocks[mRow + 2][mLine].mUsed || 
                Game::sExistentBlocks[mRow + 3][mLine].mUsed) {
                return;
            }
            break;
        case THREE:
            if (mLine == 0) {
                return;
            }
            if (Game::sExistentBlocks[mRow + 2][mLine - 1].mUsed || 
                Game::sExistentBlocks[mRow + 3][mLine].mUsed) {
                return;
            }
            break;
        case FOUR:
            if (mLine == 0) {
                return;
            }
            if (Game::sExistentBlocks[mRow + 1][mLine].mUsed || 
                Game::sExistentBlocks[mRow + 2][mLine - 1].mUsed || 
                Game::sExistentBlocks[mRow + 3][mLine].mUsed) {
                return;
            }
            break;
    }

    Block::MoveLeft();
}

/**
 * 右移。
 */
void Block3::MoveRight() {
    switch (mShape) {
        case ONE:
            if (mLine == 7) {
                return;
            }
            if (Game::sExistentBlocks[mRow + 1][mLine + 2].mUsed || 
                Game::sExistentBlocks[mRow + 2][mLine + 3].mUsed) {
                return;
            }
            break;
        case TWO:
            if (mLine == 7) {
                return;
            }
            if (Game::sExistentBlocks[mRow + 1][mLine + 2].mUsed || 
                Game::sExistentBlocks[mRow + 2][mLine + 3].mUsed || 
                Game::sExistentBlocks[mRow + 3][mLine + 2].mUsed) {
                return;
            }
            break;
        case THREE:
            if (mLine == 7) {
                return;
            }
            if (Game::sExistentBlocks[mRow + 2][mLine + 3].mUsed || 
                Game::sExistentBlocks[mRow + 3][mLine + 2].mUsed) {
                return;
            }
            break;
        case FOUR:
            if (mLine == 8) {
                return;
            }
            if (Game::sExistentBlocks[mRow + 1][mLine + 2].mUsed || 
                Game::sExistentBlocks[mRow + 2][mLine + 2].mUsed || 
                Game::sExistentBlocks[mRow + 3][mLine + 2].mUsed) {
                return;
            }
            break;
    }

    Block::MoveRight();
}

/**
 * 变形。
 */
void Block3::Transform() {
    switch (mShape) {
        case ONE:
            if (mRow == 17) {
                return;
            }
            if (Game::sExistentBlocks[mRow + 3][mLine + 1].mUsed) {
                return;
            }
            this->Erase();
            mBlocks[2][0].mUsed = FALSE;
            mBlocks[3][1].mUsed = TRUE;
            mShape = TWO;
            break;
        case TWO:
            if (mLine == -1) {
                return;
            }
            if (Game::sExistentBlocks[mRow + 2][mLine].mUsed) {
                return;
            }
            this->Erase();
            mBlocks[1][1].mUsed = FALSE;
            mBlocks[2][0].mUsed = TRUE;
            mShape = THREE;
            break;
        case THREE:
            if (mRow == 16) {
                return;
            }
            if (Game::sExistentBlocks[mRow + 1][mLine + 1].mUsed) {
                return;
            }
            this->Erase();
            mBlocks[2][2].mUsed = FALSE;
            mBlocks[1][1].mUsed = TRUE;
            mShape = FOUR;
            break;
        case FOUR:
            if (mLine == 8) {
                return;
            }
            if (Game::sExistentBlocks[mRow + 2][mLine + 2].mUsed) {
                return;
            }
            this->Erase();
            mBlocks[3][1].mUsed = FALSE;
            mBlocks[2][2].mUsed = TRUE;
            mShape = ONE;
            break;
    }

    Block::Draw();
}
